﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ST.Common.Util.Model;
using ST.Common.Util.Text;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;

namespace ST.Common.Util.Mvc
{
	/// <summary>
	/// Controler基类，如果继承此类需要自己处理异常
	/// </summary>
	public partial class BaseController : Controller, IActionFilter
	{
		protected readonly ILogger logger;

		public BaseController(ILogger<BaseController> _logger)
		{
			logger = _logger;
		}

		protected BaseController(ILogger _logger)
		{
			logger = _logger;
		}

		/// <summary>
		/// 获取当天会话的认证信息，如果解析有误或为空则抛出AuthException异常
		/// </summary>
		/// <returns></returns>
		protected virtual UserSession GetSessionFromRequest(bool cors = false)
		{
			try
			{
				return HttpContextHelper.GetSessionFromRequest(Request, cors);
			}
			catch (AuthException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw ex;
			}
		}

		/// <summary>
		/// 获取当天会话的认证信息，如果解析有误或为空则抛出AuthException异常
		/// </summary>
		/// <returns></returns>
		/// <exception cref="AuthException"></exception>
		protected virtual UserSession GetRawSessionFromRequest(bool cors = false)
		{
			try
			{
				return HttpContextHelper.GetRawSessionFromRequest(Request, cors);
			}
			catch (AuthException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw ex;
			}
		}

		/// <summary>
		/// 获取请求的IP地址
		/// </summary>
		/// <returns></returns>
		protected virtual string GetRequestIP()
		{
			string ip = string.Empty;
			StringValues _ip = Request.Headers["X-Forwarded-For"];
			if (_ip.Count > 0)
			{
				ip = _ip[0];
			}
			if (string.IsNullOrEmpty(ip))
			{
				ip = HttpContext.Connection.RemoteIpAddress.ToString();
			}
			return ip;
		}

		/// <summary>
		/// 检查ModelState，如果有错直接抛出ArgumentException异常
		/// </summary>
		protected virtual void CheckParams()
		{
			if (!ModelState.IsValid)
			{
				ModelStateEntry entry = ModelState.Values.First(m => m.ValidationState == ModelValidationState.Invalid);
				if (entry != null && entry.Errors != null && entry.Errors.Count > 0)
				{
					ModelError error = entry.Errors[0];
					if (error.Exception != null)
					{
						throw new ArgumentException("请求参数有误", error.Exception);
					}
					else
					{
						throw new ArgumentException(error.ErrorMessage);
					}
				}
				else
				{
					throw new ArgumentException("请求参数有误");
				}
			}
		}

		/// <summary>
		/// 获取枚举类型
		/// </summary>
		/// <param name="enumType"></param>
		/// <returns></returns>
		protected List<SelectListItem> GetEnums<T>(Type enumType)
		{
			List<SelectListItem> lst = new List<SelectListItem>();
			Array values = Enum.GetValues(enumType);
			foreach (object obj in values)
			{
				SelectListItem item = new SelectListItem()
				{
					Value = ((T)obj).ToString(),
					Text = obj.ToString()
				};
				lst.Add(item);
			}
			return lst;
		}

		protected List<SelectListItem> GetOptions<T>(IEnumerable<T> values)
		{
			List<SelectListItem> lst = new List<SelectListItem>();
			foreach (var v in values)
			{
				SelectListItem item = new SelectListItem()
				{
					Text = v.ToString()
				};
				item.Value = item.Text;
				lst.Add(item);
			}
			return lst;
		}

		/// <summary>
		/// 获取枚举类型
		/// </summary>
		/// <param name="enumType"></param>
		/// <returns></returns>
		protected List<SelectListItem> GetEnums(Type enumType)
		{
			return GetEnums<int>(enumType);
		}

		protected virtual T GetSearchModelFromJson<T>(JObject paras) where T : new()
		{
			T vms = new T();
			Type t = vms.GetType();
			var properties = t.GetProperties();
			foreach (var p in properties)
			{
				if (p.PropertyType == typeof(string))
				{
					p.SetValue(vms, TextHelper.GetString(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int))
				{
					p.SetValue(vms, TextHelper.GetInt(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int?))
				{
					p.SetValue(vms, TextHelper.GetIntNullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(int[]))
				{
					p.SetValue(vms, TextHelper.GetInts(paras, p.Name));
				}
				else if (p.PropertyType == typeof(decimal))
				{
					p.SetValue(vms, TextHelper.GetDecimal(paras, p.Name));
				}
				else if (p.PropertyType == typeof(decimal?))
				{
					p.SetValue(vms, TextHelper.GetDecimalNullable(paras, p.Name));
				}
				else if (p.PropertyType == typeof(DateTime))
				{
					if (p.Name.EndsWith("_e"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeEnd(paras, p.Name));
					}
					else if (p.Name.EndsWith("_s"))
					{
						p.SetValue(vms, TextHelper.GetDateTimeStart(paras, p.Name));
					}
					else
					{
						p.SetValue(vms, TextHelper.GetDateTime(paras, p.Name));
					}
				}
			}
			return vms;
		}

		protected virtual T GetSearchModelFromGetRequest<T>() where T : new()
		{
			T vms = new T();

			return vms;
		}

		protected virtual T GetSearchModelFromPostRequest<T>() where T : new()
		{
			T vms = new T();

			return vms;
		}
	}
}
